﻿using System;
using System.Collections.Generic;

namespace UniSender
{
    using IExpando = IDictionary<string, object>;
    using Expando = Dictionary<string, object>;

    /// <summary>
    /// Есть ли подтверждённое согласие подписчика
    /// </summary>
    public enum DoubleOptIn
    {
        /// <summary>
        /// Подписчик только высказал желание подписаться, будет отправлено письмо-приглашение
        /// </summary>
        NotCofirmed = 0,

        /// <summary>
        /// Уже есть согласие подписчика, при превышении суточного лимита будет отправлено письмо-приглашение
        /// </summary>
        Confirmed = 1,

        /// <summary>
        /// Уже есть согласие подписчика, при превышении суточного лимита сервис вернёт ошибку с кодом "too_many_double_optins"
        /// </summary>
        ConfirmedOrError = 2,

        /// <summary>
        /// Уже есть согласие подписчика, при превышении суточного лимита он будет добавлен со статусом "новый"
        /// </summary>
        ConfirmedOrNew = 3
    }

    /// <summary>
    /// Режим перезаписывания полей и меток
    /// </summary>
    public enum Overwrite
    {
        /// <summary>
        /// Происходит только добавление новых полей и меток, уже существующие поля сохраняют своё значение
        /// </summary>
        AddNew = 0,

        /// <summary>
        /// Все старые поля удаляются и заменяются новыми, все старые метки также удаляются и заменяются новыми
        /// </summary>
        ReplaceAll = 1,

        /// <summary>
        /// Заменяются значения переданных полей, существующие поля сохраняются, метки, если переданы, перезаписываются
        /// </summary>
        ReplaceExists = 2
    }

    /// <summary>
    /// Параметры подписки пользователя
    /// </summary>
    public class SubscribeConfig
    {
        private List<long> lists = new List<long>();
        private Expando fields = new Expando();

        /// <summary>
        /// Параметр list_ids,
        /// коды списков, в которые надо добавить подписчика
        /// </summary>
        public virtual IList<long> ListIds
        {
            get { return lists; }
        }

        /// <summary>
        /// Параметр contact,
        /// массив дополнительных полей
        /// </summary>
        /// <remarks>
        /// Присвоение словаря в это свойство добавляет поля в коллекцию, а не заменяет её
        /// </remarks>
        public virtual IExpando Fields
        {
            get { return fields; }
            set { fields.Update(value); }
        }

        /// <summary>
        /// Параметр tags,
        /// метки, которые добавляются к подписчику
        /// </summary>
        public virtual string[] Tags { get; set; }

        /// <summary>
        /// Параметр request_ip,
        /// IP-адрес подписчика, с которого поступила просьба о подписке, в формате "XXX.XXX.XXX.XXX"
        /// </summary>
        public virtual string RequestIP { get; set; }

        /// <summary>
        /// Параметр request_time,
        /// дата и время поступления просьбы о подписке
        /// </summary>
        public virtual DateTime? RequestTime { get; set; }

        /// <summary>
        /// Параметр double_optin,
        /// есть ли подтверждённое согласие подписчика, и что делать, если превышен лимит подписок
        /// </summary>
        public virtual DoubleOptIn? DoubleOptIn { get; set; }

        /// <summary>
        /// Параметр confirm_ip,
        /// IP-адрес подписчика, с которого поступило подтверждение подписки, в формате "XXX.XXX.XXX.XXX"
        /// </summary>
        /// <remarks>
        /// Игнорируется при DoubleOptIn.NotCofirmed
        /// </remarks>
        public virtual string ConfirmIP { get; set; }

        /// <summary>
        /// Параметр confirm_time,
        /// дата и время подтверждения подписки
        /// </summary>
        /// <remarks>
        /// Игнорируется при DoubleOptIn.NotCofirmed
        /// </remarks>
        public virtual DateTime? ConfirmTime { get; set; }

        /// <summary>
        /// Параметр overwrite,
        /// режим перезаписывания полей и меток
        /// </summary>
        public virtual Overwrite? Overwrite { get; set; }

        public SubscribeConfig(long[] listIds, string email, string phone)
        {
            lists.AddRange(listIds);
            if (!String.IsNullOrEmpty(email))
                fields["email"] = email;
            if (!String.IsNullOrEmpty(phone))
                fields["phone"] = phone;
        }

        public SubscribeConfig(long listId, string email, string phone)
            : this(new long[] { listId }, email, phone)
        { }

        public virtual IExpando Serialize()
        {
            Expando args = new Expando();

            args["list_ids"] = lists.ToArray();
            args["fields"] = fields;
            args["tags"] = Tags;
            args["request_ip"] = RequestIP;
            args["request_time"] = RequestTime.Stringify();
            args["confirm_ip"] = ConfirmIP;
            args["request_time"] = ConfirmTime.Stringify();
            if (DoubleOptIn != null)
                args["double_optin"] = (int)DoubleOptIn.Value;
            if (Overwrite != null)
                args["overwrite"] = (int)Overwrite.Value;

            return args;
        }
    }
}
